package com.itedge.solutionmanager.web.convert;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import org.springframework.format.AnnotationFormatterFactory;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.Parser;
import org.springframework.format.Printer;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.datetime.joda.JodaTimeFormattingConfigurer;
import org.springframework.format.number.NumberFormatAnnotationFormatterFactory;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
import org.springframework.util.ClassUtils;

/**
 * Overrides default implementation and set ISO formatting for dates to true
 * 
 * @author jhe
 *
 */
public class ISOFormattingConversionServiceBean extends FormattingConversionServiceFactoryBean {
	
	private static final boolean jodaTimePresent = ClassUtils.isPresent(
			"org.joda.time.LocalDate", FormattingConversionService.class.getClassLoader());
	
	/**
	 * Install formatters and set ISO formatting to true 
	 */
	protected void installFormatters(FormatterRegistry registry) {
		registry.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory());
		if (jodaTimePresent) {
			JodaTimeFormattingConfigurer configurer = new JodaTimeFormattingConfigurer();
			configurer.setUseIsoFormat(true);
			configurer.installJodaTimeFormatting(registry);			
		}
		else {
			registry.addFormatterForFieldAnnotation(new NoJodaDateTimeFormatAnnotationFormatterFactory());
		}
	}
	
	/**
	 * Dummy AnnotationFormatterFactory that simply fails if @DateTimeFormat is being used
	 * without the JodaTime library being present.
	 */
	private static final class NoJodaDateTimeFormatAnnotationFormatterFactory
			implements AnnotationFormatterFactory<DateTimeFormat> {

		private final Set<Class<?>> fieldTypes;

		public NoJodaDateTimeFormatAnnotationFormatterFactory() {
			Set<Class<?>> rawFieldTypes = new HashSet<Class<?>>(4);
			rawFieldTypes.add(Date.class);
			rawFieldTypes.add(Calendar.class);
			rawFieldTypes.add(Long.class);
			this.fieldTypes = Collections.unmodifiableSet(rawFieldTypes);
		}

		public Set<Class<?>> getFieldTypes() {
			return this.fieldTypes;
		}

		public Printer<?> getPrinter(DateTimeFormat annotation, Class<?> fieldType) {
			throw new IllegalStateException("JodaTime library not available - @DateTimeFormat not supported");
		}

		public Parser<?> getParser(DateTimeFormat annotation, Class<?> fieldType) {
			throw new IllegalStateException("JodaTime library not available - @DateTimeFormat not supported");
		}
	}

}
